package com.rbac.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rbac.admin.config.JwtTokenUtil;
import com.rbac.admin.entity.SysUser;
import com.rbac.admin.entity.SysUserRole;
import com.rbac.admin.mapper.SysUserMapper;
import com.rbac.admin.mapper.SysUserRoleMapper;
import com.rbac.admin.model.dto.LoginDTO;
import com.rbac.admin.model.dto.RegisterDTO;
import com.rbac.admin.model.dto.UserDTO;
import com.rbac.admin.model.vo.LoginVO;
import com.rbac.admin.model.vo.UserVO;
import com.rbac.admin.service.CacheService;
import com.rbac.admin.service.SysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户服务实现类
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private SysUserRoleMapper userRoleMapper;
    
    @Autowired
    private CacheService cacheService;
    
    @Value("${cache.expiration.user}")
    private long userCacheExpiration;
    
    // 缓存key前缀
    private static final String USER_CACHE_KEY = "user:";
    private static final String USER_TOKEN_CACHE_KEY = "user:token:";

    @Override
    public LoginVO login(LoginDTO loginDTO) {
        // 进行用户认证
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                loginDTO.getUsername(), loginDTO.getPassword());
        Authentication authentication = authenticationManager.authenticate(authenticationToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);

        // 生成JWT token
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        String token = jwtTokenUtil.generateToken(userDetails);

        // 查询用户信息
        SysUser user = getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, loginDTO.getUsername()));
        
        // 更新最后登录时间
        user.setLastLoginTime(LocalDateTime.now());
        updateById(user);

        // 查询用户角色和权限
        List<String> roles = baseMapper.selectRolesByUserId(user.getId());
        List<String> permissions = baseMapper.selectPermissionsByUserId(user.getId());

        // 构建返回结果
        LoginVO loginVO = LoginVO.builder()
                .userId(user.getId())
                .username(user.getUsername())
                .nickname(user.getNickname())
                .avatar(user.getAvatar())
                .token(token)
                .roles(roles)
                .permissions(permissions)
                .build();
                
        // 将用户信息和token存入缓存
        cacheService.set(USER_CACHE_KEY + user.getId(), user, userCacheExpiration);
        cacheService.set(USER_TOKEN_CACHE_KEY + token, loginVO, userCacheExpiration);
        
        return loginVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserVO register(RegisterDTO registerDTO) {
        // 检查用户名是否已存在
        long count = count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, registerDTO.getUsername()));
        if (count > 0) {
            throw new RuntimeException("用户名已存在");
        }

        // 创建用户
        SysUser user = new SysUser();
        BeanUtils.copyProperties(registerDTO, user);
        // 密码加密
        user.setPassword(passwordEncoder.encode(registerDTO.getPassword()));
        user.setStatus(1);
        save(user);

        // 分配默认角色（普通用户）
        SysUserRole userRole = new SysUserRole();
        userRole.setUserId(user.getId());
        userRole.setRoleId(2L); // 默认角色ID为2（普通用户）
        userRoleMapper.insert(userRole);

        // 返回用户信息
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }

    @Override
    public UserVO getUserInfo(Long userId) {
        // 尝试从缓存获取
        SysUser user = cacheService.get(USER_CACHE_KEY + userId);
        if (user == null) {
            // 缓存未命中，查询数据库
            user = getById(userId);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }
            // 存入缓存
            cacheService.set(USER_CACHE_KEY + userId, user, userCacheExpiration);
        }
        
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }

    @Override
    public boolean updateUserInfo(UserDTO userDTO) {
        SysUser user = getById(userDTO.getId());
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        BeanUtils.copyProperties(userDTO, user);
        boolean result = updateById(user);
        
        // 更新缓存
        if (result) {
            cacheService.set(USER_CACHE_KEY + user.getId(), user, userCacheExpiration);
        }
        
        return result;
    }

    @Override
    public Page<UserVO> listUserPage(Integer pageNum, Integer pageSize, String keyword) {
        // 分页查询
        Page<SysUser> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        
        // 添加查询条件
        if (StringUtils.hasText(keyword)) {
            queryWrapper.like(SysUser::getUsername, keyword)
                    .or().like(SysUser::getNickname, keyword)
                    .or().like(SysUser::getEmail, keyword)
                    .or().like(SysUser::getPhone, keyword);
        }
        
        // 排序
        queryWrapper.orderByDesc(SysUser::getCreateTime);
        
        // 执行查询
        page = page(page, queryWrapper);
        
        // 转换结果
        Page<UserVO> resultPage = new Page<>(pageNum, pageSize, page.getTotal());
        List<UserVO> userVOList = page.getRecords().stream().map(user -> {
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(user, userVO);
            return userVO;
        }).collect(Collectors.toList());
        resultPage.setRecords(userVOList);
        
        return resultPage;
    }

    @Override
    public List<Long> getRoleIdsByUserId(Long userId) {
        LambdaQueryWrapper<SysUserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUserRole::getUserId, userId);
        List<SysUserRole> userRoles = userRoleMapper.selectList(queryWrapper);
        return userRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean assignRoles(Long userId, List<Long> roleIds) {
        // 先删除原有角色关联
        LambdaQueryWrapper<SysUserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUserRole::getUserId, userId);
        userRoleMapper.delete(queryWrapper);
        
        // 添加新的角色关联
        if (roleIds != null && !roleIds.isEmpty()) {
            List<SysUserRole> userRoles = new ArrayList<>();
            for (Long roleId : roleIds) {
                SysUserRole userRole = new SysUserRole();
                userRole.setUserId(userId);
                userRole.setRoleId(roleId);
                userRoles.add(userRole);
            }
            // 批量插入
            for (SysUserRole userRole : userRoles) {
                userRoleMapper.insert(userRole);
            }
        }
        
        // 清除用户相关缓存
        SysUser user = getById(userId);
        if (user != null) {
            clearUserCache(user.getUsername());
        }
        
        return true;
    }
    
    @Override
    public void clearUserCache(String username) {
        // 查询用户信息
        SysUser user = getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
        if (user != null) {
            // 删除用户信息缓存
            cacheService.delete(USER_CACHE_KEY + user.getId());
            
            // 删除用户token相关缓存（模式匹配删除）
            cacheService.deleteByPattern(USER_TOKEN_CACHE_KEY + "*");
            
            // 删除用户菜单和权限缓存
            cacheService.delete("menu:user:" + user.getId());
            cacheService.delete("permission:user:" + user.getId());
        }
    }
}